﻿namespace A2DFramework.OSGI.Processors
{
    using A2DFramework.OSGI.Configuration;
    using A2DFramework.OSGI.ConnectionChannel;
    using A2DFramework.OSGI.Helps;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.CompilerServices;

    public class BundleRuntimeProcessor : MarshalByRefObject, IDisposable
    {
        private GlobalSettingInfo globalConfig;
        private Dictionary<string, List<string>> map_ServiceRequestType_DLLFileName;
        private Dictionary<string, List<string>> map_ServiceRequestType_ModuleName;
        private Dictionary<string, List<string>> map_ServiceRequestType_ProviderType;
        private Dictionary<string, List<string>> map_ServiceRequestType_SPDLLFileName;
        private List<ModuleInfo> moduleConfigs;
        private List<ModuleSandBox> moduleSandBoxes;

        public BundleRuntimeProcessor()
        {
            this.map_ServiceRequestType_ModuleName = new Dictionary<string, List<string>>();
            this.map_ServiceRequestType_DLLFileName = new Dictionary<string, List<string>>();
            this.map_ServiceRequestType_SPDLLFileName = new Dictionary<string, List<string>>();
            this.map_ServiceRequestType_ProviderType = new Dictionary<string, List<string>>();
        }

        public BundleRuntimeProcessor(GlobalSettingInfo globalSetting, List<ModuleInfo> modules)
        {
            this.map_ServiceRequestType_ModuleName = new Dictionary<string, List<string>>();
            this.map_ServiceRequestType_DLLFileName = new Dictionary<string, List<string>>();
            this.map_ServiceRequestType_SPDLLFileName = new Dictionary<string, List<string>>();
            this.map_ServiceRequestType_ProviderType = new Dictionary<string, List<string>>();
            Current = this;
            this.InAppDomainName = AppDomain.CurrentDomain.FriendlyName;
            this.moduleConfigs = new List<ModuleInfo>();
            this.moduleConfigs.AddRange(modules.AsReadOnly().ToList<ModuleInfo>());
            this.globalConfig = globalSetting;
            List<ModuleSandBox> list = new List<ModuleSandBox>();
            foreach (ModuleInfo info in this.moduleConfigs)
            {
                ModuleSandBox item = new ModuleSandBox(info);
                list.Add(item);
            }
            this.moduleSandBoxes = list;
        }

        internal void AddServiceMap(string moduleName, string requestType, string providerType, string requestTypeDllFileName, string providerTypeDllFileName)
        {
            this.AddServiceProviderMapInfo(requestType, providerType);
            this.AddServiceModuleNameMapInfo(requestType, moduleName);
            this.AddServiceModuleDllFileNameMapInfo(requestType, requestTypeDllFileName);
            this.AddServiceModuleSPDllFileNameMapInfo(requestType, providerTypeDllFileName);
        }

        private void AddServiceModuleDllFileNameMapInfo(string requestType, string requestTypeDllFileName)
        {
            if (!this.map_ServiceRequestType_DLLFileName.ContainsKey(requestType))
            {
                this.map_ServiceRequestType_DLLFileName.Add(requestType, new List<string>());
            }
            List<string> list = this.map_ServiceRequestType_DLLFileName[requestType];
            if (!list.Contains(requestTypeDllFileName))
            {
                list.Add(requestTypeDllFileName);
            }
            this.map_ServiceRequestType_DLLFileName[requestType] = list;
        }

        private void AddServiceModuleNameMapInfo(string requestType, string moduleName)
        {
            if (!this.map_ServiceRequestType_ModuleName.ContainsKey(requestType))
            {
                this.map_ServiceRequestType_ModuleName.Add(requestType, new List<string>());
            }
            List<string> list = this.map_ServiceRequestType_ModuleName[requestType];
            if (!list.Contains(moduleName))
            {
                list.Add(moduleName);
            }
            this.map_ServiceRequestType_ModuleName[requestType] = list;
        }

        private void AddServiceModuleSPDllFileNameMapInfo(string requestType, string providerTypeDllFileName)
        {
            if (!this.map_ServiceRequestType_SPDLLFileName.ContainsKey(requestType))
            {
                this.map_ServiceRequestType_SPDLLFileName.Add(requestType, new List<string>());
            }
            List<string> list = this.map_ServiceRequestType_SPDLLFileName[requestType];
            if (!list.Contains(providerTypeDllFileName))
            {
                list.Add(providerTypeDllFileName);
            }
            this.map_ServiceRequestType_SPDLLFileName[requestType] = list;
        }

        private void AddServiceProviderMapInfo(string requestType, string providerType)
        {
            if (!this.map_ServiceRequestType_ProviderType.ContainsKey(requestType))
            {
                this.map_ServiceRequestType_ProviderType.Add(requestType, new List<string>());
            }
            List<string> list = this.map_ServiceRequestType_ProviderType[requestType];
            if (!list.Contains(providerType))
            {
                list.Add(providerType);
            }
            this.map_ServiceRequestType_ProviderType[requestType] = list;
        }

        internal object CreateNewInstance(RemoteServiceInfo rsInfo)
        {
            string url = string.Format("tcp://{0}:{1}/OSGI", rsInfo.TargetIP, rsInfo.TargetPort);
            RemoteServiceDto dto = ((IOSGICommunicator) Activator.GetObject(typeof(IOSGICommunicator), url)).OpenService(rsInfo.RequestServiceType);
            string moduleName = this.GetModuleName(rsInfo.RequestServiceType);
            string dllName = this.GetDllName(rsInfo.RequestServiceType);
            string str4 = string.Format("tcp://{0}:{1}/{2}", rsInfo.TargetIP, dto.Port, dto.ServiceUri);
            return Activator.GetObject(A2DFramework.OSGI.Helps.TypeHelper.ParseType(moduleName, dllName, rsInfo.RequestServiceType), str4);
        }

        internal object CreateNewInstance(string moduleName, string classType)
        {
            return this.moduleSandBoxes.First<ModuleSandBox>(t => (t.ModuleName == moduleName)).CreateInstance(classType);
        }

        internal void DeleteServiceMap(string moduleName, string requestType, string providerType)
        {
            this.DeleteServiceProviderMapInfo(requestType, providerType);
            this.DeleteServiceModuleNameMapInfo(requestType, moduleName);
            this.DeleteServiceModuleDllFileNameMapInfo(requestType);
        }

        private void DeleteServiceModuleDllFileNameMapInfo(string requestType)
        {
            if (this.map_ServiceRequestType_DLLFileName.ContainsKey(requestType))
            {
                this.map_ServiceRequestType_DLLFileName.Remove(requestType);
                if (this.map_ServiceRequestType_SPDLLFileName.ContainsKey(requestType))
                {
                    this.map_ServiceRequestType_SPDLLFileName.Remove(requestType);
                }
            }
        }

        private void DeleteServiceModuleNameMapInfo(string requestType, string moduleName)
        {
            if (this.map_ServiceRequestType_ModuleName.ContainsKey(requestType))
            {
                this.map_ServiceRequestType_ModuleName[requestType].Remove(moduleName);
            }
        }

        private void DeleteServiceProviderMapInfo(string requestType, string providerType)
        {
            if (this.map_ServiceRequestType_ProviderType.ContainsKey(requestType))
            {
                this.map_ServiceRequestType_ProviderType[requestType].Remove(providerType);
            }
        }

        public void Dispose()
        {
            foreach (ModuleSandBox box in this.moduleSandBoxes)
            {
                box.Dispose();
            }
        }

        public string GetDllName(string requestType)
        {
            List<string> serviceDllFileNames = this.GetServiceDllFileNames(requestType);
            string str = null;
            if (serviceDllFileNames.Count > 0)
            {
                str = serviceDllFileNames[0];
            }
            return str;
        }

        public BundleRuntimeProcessor GetGlobalProcessor()
        {
            return Current;
        }

        internal ModuleInfo GetModuleInfo(string moduleName)
        {
            foreach (ModuleInfo info in this.moduleConfigs)
            {
                if (info.Name == moduleName)
                {
                    return info;
                }
            }
            return null;
        }

        public string GetModuleName(string requestType)
        {
            List<string> serviceModuleNames = this.GetServiceModuleNames(requestType);
            string str = null;
            if (serviceModuleNames.Count > 0)
            {
                str = serviceModuleNames[0];
            }
            return str;
        }

        internal RemoteServiceInfo GetRemoteServiceMap(string requestType)
        {
            foreach (RemoteServiceInfo info in this.globalConfig.RemoteServices)
            {
                if (info.RequestServiceType == requestType)
                {
                    return info;
                }
            }
            return null;
        }

        private List<string> GetServiceDllFileNames(string requestType)
        {
            List<string> list = new List<string>();
            if (!this.map_ServiceRequestType_DLLFileName.ContainsKey(requestType))
            {
                return list;
            }
            return this.map_ServiceRequestType_DLLFileName[requestType];
        }

        internal List<KeyValuePair<string, string>> GetServiceMap(string requestType)
        {
            List<string> serviceModuleNames = this.GetServiceModuleNames(requestType);
            List<string> serviceProviderTypes = this.GetServiceProviderTypes(requestType);
            List<KeyValuePair<string, string>> list3 = new List<KeyValuePair<string, string>>();
            for (int i = 0; i < serviceModuleNames.Count; i++)
            {
                string key = serviceModuleNames[i];
                string str2 = serviceProviderTypes[i];
                KeyValuePair<string, string> item = new KeyValuePair<string, string>(key, str2);
                list3.Add(item);
            }
            return list3;
        }

        private List<string> GetServiceModuleNames(string requestType)
        {
            List<string> list = new List<string>();
            if (!this.map_ServiceRequestType_ModuleName.ContainsKey(requestType))
            {
                return list;
            }
            return this.map_ServiceRequestType_ModuleName[requestType];
        }

        public string GetServiceProviderDllName(string requestType)
        {
            List<string> serviceSPDllFileNames = this.GetServiceSPDllFileNames(requestType);
            string str = null;
            if (serviceSPDllFileNames.Count > 0)
            {
                str = serviceSPDllFileNames[0];
            }
            return str;
        }

        public string GetServiceProviderType(string requestType)
        {
            List<string> serviceProviderTypes = this.GetServiceProviderTypes(requestType);
            if (serviceProviderTypes.Count > 0)
            {
                return serviceProviderTypes[0];
            }
            return "";
        }

        private List<string> GetServiceProviderTypes(string requestType)
        {
            List<string> list = new List<string>();
            if (!this.map_ServiceRequestType_ProviderType.ContainsKey(requestType))
            {
                return list;
            }
            return this.map_ServiceRequestType_ProviderType[requestType];
        }

        private List<string> GetServiceSPDllFileNames(string requestType)
        {
            List<string> list = new List<string>();
            if (!this.map_ServiceRequestType_SPDLLFileName.ContainsKey(requestType))
            {
                return list;
            }
            return this.map_ServiceRequestType_SPDLLFileName[requestType];
        }

        public void Initialize()
        {
            RemotingServiceHelper.RegisterOSGIService(typeof(OSGICommunicatorImpl).FullName, this.globalConfig.ServicePort, "OSGI");
            foreach (ModuleSandBox box in this.moduleSandBoxes)
            {
                box.Init();
            }
            foreach (ModuleSandBox box in this.moduleSandBoxes)
            {
                box.Start();
            }
        }

        internal void RegisterOSGIService(string requestServiceType, int prot, string serviceUri)
        {
            string moduleName = this.GetServiceModuleNames(requestServiceType).First<string>();
            this.moduleSandBoxes.First<ModuleSandBox>(t => (t.ModuleName == moduleName)).RegisterOSGIService(requestServiceType, this.GetServiceProviderType(requestServiceType), prot, serviceUri);
        }

        public void Stop()
        {
            foreach (ModuleSandBox box in this.moduleSandBoxes)
            {
                box.Stop();
            }
        }

        public static BundleRuntimeProcessor Current { get; set; }

        public string InAppDomainName { get; set; }
    }
}

